//! # Tray - 系统托盘模块

use tauri::{
    AppHandle, CustomMenuItem, Manager, Runtime, SystemTray, SystemTrayEvent, SystemTrayMenu,
    SystemTrayMenuItem,
};

use crate::{
    event::{ListenMP4GameEvent, MP4GameEvent, WINDOW_VISIBILITY},
    setup::add_setup_task,
    util::set_window_visibility,
};

/// Tauri MP4Game 系统托盘扩展
pub trait TauriMP4GameTray<R: Runtime> {
    /// 注册系统托盘
    fn invoke_mp4game_tray(self) -> tauri::Builder<R>;
}

impl TauriMP4GameTray<tauri::Wry> for tauri::Builder<tauri::Wry> {
    /// 注册系统托盘
    fn invoke_mp4game_tray(self) -> tauri::Builder<tauri::Wry> {
        // 菜单项
        let hide = CustomMenuItem::new("hide", "隐藏窗口");
        let quit = CustomMenuItem::new("quit", "退出");

        // 创建系统托盘菜单
        let tray_menu = SystemTrayMenu::new()
            .add_item(hide)
            .add_native_item(SystemTrayMenuItem::Separator)
            .add_item(quit);

        // 创建系统托盘
        let system_tray = SystemTray::new()
            .with_menu(tray_menu)
            .with_tooltip("MP4Game");

        // 监听部分托盘相关事件
        add_setup_task(|app| {
            let item_tray = app.tray_handle().get_item("hide");
            app.listen_mp4game_event(WINDOW_VISIBILITY, move |event| {
                log::trace!("系统托盘接收到窗口可见性事件：{event:?}");

                // 判断事件类型
                if let MP4GameEvent::WindowVisibility(visible) = event {
                    Ok(visible)
                } else {
                    Err("MP4GameEvent 事件类型错误".to_string())
                }
                // 根据窗口可见性设置托盘标题
                .and_then(|visible| {
                    item_tray
                        .set_title(if visible {
                            "隐藏窗口"
                        } else {
                            "显示窗口"
                        })
                        .map_err(|e| e.to_string())
                })
                // 打印错误日志
                .or_else(|e| -> Result<(), ()> {
                    log::error!("设置托盘标题失败：{e}");
                    Ok(())
                })
                .unwrap();
            });

            Ok(())
        })
        .unwrap();

        // 显示或隐藏窗口
        let hide_or_show_window = |app: &AppHandle, toggle: bool| {
            // 获取窗口
            app.get_window("main")
                .ok_or("窗口 main 获取失败".to_string())
                // 获取窗口可见性
                .and_then(|window| {
                    window
                        .is_visible()
                        .map(|visible| (window, visible))
                        .map_err(|e| e.to_string())
                })
                // toggle = true，切换窗口可见性
                // toggle = false，显示窗口
                .and_then(|(window, visible)| set_window_visibility(&window, !(toggle && visible)))
                // 打印错误日志
                .or_else(|e| -> Result<(), ()> {
                    log::error!("设置窗口 main 的可见性失败：{e}");
                    Ok(())
                })
                .unwrap();
        };

        // 设置系统托盘
        self.system_tray(system_tray)
            .on_system_tray_event(move |app, event| match event {
                SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
                    "hide" => hide_or_show_window(app, true),
                    "quit" => app.exit(0),
                    _ => {}
                },
                SystemTrayEvent::DoubleClick { .. } => hide_or_show_window(app, false),
                _ => {}
            })
    }
}
